# -*- encoding: utf-8 -*-

"""
=============================
this is a feibot product,
all rights reserved.
www.feibot.com
@author: Gu Tianyuan
@email: g@feibot.com
@time: ${DATE}:${TIME}
@product: ${PRODUCT_NAME}
=============================
"""
import threading
import time

import gtyTools.gtyTypes
import gtyTools.gtyLog
import SocketWorker
import traceback
import os

from gtySocket import socketTools


class FeibotSocket:

    def __init__(self, eventQ):
        self.eventQ = eventQ

        # 配置的控制接口
        self.configHandlers = gtyTools.gtyTypes.ConfigHandlers()
        self.socketType = None
        self.targetIp = None
        self.targetPort = None
        self.localPort = None
        self.enRespond = None
        # socketWorker
        self.socketWorker = None

        # 事件驱动引擎
        self.eventEngine = threading.Thread(target=self.eventEngine)
        self.eventEngine.start()

        self.reloadConfigAndConnect()
        # 解包socket指令
        self.parseHandler = socketTools.ParseSocket()
        self.buildHandler = socketTools.SocketBuild()
        # 记录log
        gtyTools.gtyLog.log.write(__file__, 'start: ', self.socketType, self.targetIp, self.targetPort)

        self.dateTimeStringFormat = self.configHandlers.machine.read('IO', 'dateTimeReformat')
        self.useIsoDateTimeFormat = self.configHandlers.machine.read('IO', "useIsoDateTimeFormat", "string", "")
        self.isoTimeZoneString = self.configHandlers.machine.read('IO', "isoTimeZoneString", "string", "")
        self.RaceTecEnable = self.configHandlers.machine.read("RaceTec", "enable", "int", 0)
    # 重新加载
    def reloadConfigAndConnect(self):
        self.configHandlers.machine.openConfigFile()
        self.socketType = self.configHandlers.machine.read('socket', 'type')
        self.targetIp = self.configHandlers.machine.read('socket', 'targetIp')
        self.targetPort = self.configHandlers.machine.read('socket', 'targetPort')
        self.localPort = self.configHandlers.machine.read('socket', 'localPort')
        self.enRespond = self.configHandlers.machine.read('socket', 'enRespond', 'int')

        # socketWorker
        try:
            self.socketWorker.disconnect()
        except:
            pass
        self.socketWorker = SocketWorker.SocketWorker(self.socketType, self.targetIp, self.targetPort, self.localPort)
        connectState = self.socketWorker.connect()
        self.configHandlers.state.write('machine', 'socketConnectState', connectState, 'bool')
        self.sendEvent('UI', 'ui_socketConnectedResult', connectState)

    def work(self):
        while True:
            time.sleep(0.01)
            try:
                if self.socketWorker.receive():
                    self.sendEvent('SOCKET', 'socket_receive', [])
            except Exception as e:
                print(e)
                print(__file__, 'socket run...')

    def eventEngine(self):
        while True:
            time.sleep(0.001)

            if 'SOCKET' not in self.eventQ.keys():
                continue

            if not self.eventQ['SOCKET'].empty():  # 事件队列非空
                try:
                    event = self.eventQ['SOCKET'].get(block=True, timeout=1)  # 获取队列中的事件 超时1秒
                    self.handleEventResult(event)
                except Exception as e:
                    traceback.extract_stack()
                    print(__file__, 'eventEngine error', e)
            else:
                pass

    # 发出事件
    def sendEvent(self, task, eventName, eventData=None):
        if eventData is None:
            eventData = []
        e = [eventName, eventData]
        try:
            if task.upper() in self.eventQ.keys():
                self.eventQ[task.upper()].put(e)
        except Exception as e:
            print(e)

    def handleEventResult(self, event):
        task = event[0]
        data = event[1]
        if task == 'socket_send':
            # if 'heartBeat' not in data:
            #     print(__file__, data)
            if data[0].upper() == 'EPC':
                if self.useIsoDateTimeFormat != "1":
                    if self.dateTimeStringFormat == "blank space":
                        data[1] = data[1].replace('_', ' ')
                    elif self.dateTimeStringFormat == "T":
                        data[1] = data[1].replace('_', 'T')
                else:
                    if self.RaceTecEnable == 1:
                        if self.dateTimeStringFormat == "blank space":
                            data[1] = data[1].replace('_', ' ')
                        elif self.dateTimeStringFormat == "T":
                            data[1] = data[1].replace('_', 'T')
                    else:
                        data[1] = data[1].replace('_', ' ')
                        data[1] = data[1] + self.isoTimeZoneString  # 此处添加时区有问题，待修改
            cmd = self.buildHandler.buildSocket(data[0], data[1])
            self.socketWorker.send(cmd)
            return
        if task == 'socket_receive':
            try:
                self.handleReceive()
            except Exception as e:
                print(__file__, 'receive socket error', e)
            return
        if task == 'socket_connect':
            connectState = self.socketWorker.connect()
            self.configHandlers.state.write('machine', 'socketConnectState', connectState, 'bool')
            self.sendEvent('UI', 'ui_socketConnectedResult', connectState)
            return
        if task == 'socket_disconnect':
            connectState = self.socketWorker.disconnect()
            self.configHandlers.state.write('machine', 'socketConnectState', not connectState, 'bool')
            self.sendEvent('UI', 'ui_socketConnectedResult', not connectState)
            return
        if task == 'socket_reconnect':
            connectState = self.socketWorker.reconnect()
            self.configHandlers.state.write('machine', 'socketConnectState', connectState, 'bool')
            self.sendEvent('UI', 'ui_socketConnectedResult', connectState)
            return
        if task == 'socket_getConnectionState':
            self.socketWorker.getState()
            return
        if task == 'socket_loadConfigAndConnect':
            self.reloadConfigAndConnect()
            return

    # 处理接收
    def handleReceive(self):
        print(__file__, 'socket rx: ' + self.socketWorker.socketObj.rxBuf)
        socketCmds = self.socketWorker.socketObj.rxBuf.split(';')
        self.socketWorker.socketObj.rxBuf = ""
        for socketCmd in socketCmds:
            if len(socketCmd) == 0:
                return
            res = self.parseHandler.parseSocket(socketCmd)
            print(__file__, 'res', res)
            if len(res) != 3:
                continue
            cmd = res[0].upper()
            cmdId = res[1]
            data = res[2]
            d = data.split(',')
            if cmd:
                if cmd == 'readerOpen'.upper():  # 这里的参数是一个数组，['1',cmd]，这里cmd=on，开启，cmd=off，关闭，x不指定
                    if self.configHandlers.machine.read('machine', 'hardwareType', 'string') == "A400":
                        self.sendEvent('UI', 'ui_startOrStropReading', [data, 'onFromWeb'])
                    else:
                        self.sendEvent('UI', 'ui_startOrStropReading', [data, 'on'])
                    continue

                if cmd == 'readerStop'.upper():  # 这里的参数是一个数组，['1',cmd]，这里cmd=on，开启，cmd=off，关闭，x不指定
                    if self.configHandlers.machine.read('machine', 'hardwareType', 'string') == "A400":
                        self.sendEvent('UI', 'ui_startOrStropReading', [data, 'offFromWeb'])
                    else:
                        self.sendEvent('UI', 'ui_startOrStropReading', [data, 'off'])
                    continue

                if cmd == 'setDate'.upper():
                    year = int(d[0]) if int(d[0]) < 2000 else int(d[0]) - 2000
                    month = int(d[1])
                    day = int(d[2])
                    if 20 <= year <= 30 and 1 <= month <= 12 and 1 <= day <= 31:
                        print(__file__, 'set date:', year, month, day)
                        self.sendEvent("UART", "uart_setDs3231Date", [year, month, day])
                    continue

                if cmd == 'setTime'.upper():
                    hour = int(d[0])
                    minute = int(d[1])
                    second = int(d[2])
                    centiSecond = int(d[3])
                    if 0 <= hour <= 23 and 0 <= minute <= 59 and 0 <= second <= 59 and 0 <= centiSecond <= 99:
                        self.sendEvent("UART", "uart_setDs3231Time", [int(d[0]), int(d[1]), int(d[2]), int(d[3])])
                    continue

                if cmd == 'getGunTime'.upper():
                    self.sendEvent("UI", "ui_socketGetGunTime", True)
                    continue

                if cmd == 'packDataSection'.upper():
                    if len(d) == 2:
                        self.sendEvent("IO", "file_packDataSection", [d[0], d[1]])
                    elif len(d) == 1 and d[0] == 'x':
                        self.sendEvent("IO", "file_packDataSection", [])
                    continue

                if cmd == 'deleteData'.upper():
                    self.sendEvent("IO", "io_deleteDataFile", [])
                    continue

                # 重新拉取数据
                if cmd.upper() == 'rewindData'.upper():
                    if len(d) == 2:
                        self.sendEvent("IO", "io_rewindData", [d[0], d[1]])
                    elif len(d) == 1 and d[0] == 'x':
                        self.sendEvent("IO", "io_rewindData", [])
                    print(__file__, "socket rewindData")
                    continue

                # 有源系统
                if cmd.upper() == 'loopEnable'.upper():
                    print(__file__, "UART", 'uart_active_lfControl', [int(d[0]), 1])
                    self.sendEvent("UART", 'uart_active_lfControl', [int(d[0]), 1])
                    continue

                if cmd.upper() == 'loopDisable'.upper():
                    print(__file__, "UART", 'uart_active_lfControl', [int(d[0]), 0])
                    self.sendEvent("UART", 'uart_active_lfControl', [int(d[0]), 0])
                    continue

                if cmd.upper() == 'setActiveChannel'.upper():
                    channel = int(d[0])
                    if channel < 0:
                        channel = 0
                    if channel >= 5:
                        channel = 5
                    self.sendEvent("UART", 'uart_active_lfChannel', [1, channel])
                    continue

                if cmd.upper() == 'setActivePower'.upper():
                    power = int(d[0])
                    if power < 0:
                        power = 0
                    if power > 100:
                        power = 100
                    self.sendEvent("UART", 'uart_active_lfPower', [1, power])
                    continue

                if cmd.upper() == 'setReaderPower'.upper():
                    readerId = int(d[0])
                    power = int(d[1])
                    if self.configHandlers.machine.read('machine', 'hardwareType', 'string') == "A400" or self.configHandlers.machine.read('machine', 'machineState', 'string') == "Active":
                        if power < 0:
                            power = 0
                        if power > 100:
                            power = 100
                            self.sendEvent("UART", 'uart_active_lfPower', [1, power])
                    if self.configHandlers.machine.read('machine', 'machineState', 'string') == "Passive" or self.configHandlers.machine.read('machine', 'hardwareType', 'string') == "F800":
                        if power < 1:
                            power = 1
                        if power > 33:
                            power = 33
                        self.sendEvent('UART', 'uart_setReaderPower', [int(readerId) + 2, power])  # 设置读卡功率
                        self.sendEvent('UI', 'ui_updateReaderPower', [int(readerId), power])
                    else:
                        pass
                    continue
                if cmd.upper() == 'setGateTime'.upper():
                    gateTime = float(d[0])
                    self.sendEvent('UI', 'ui_setGateTime', gateTime)
                    continue
                # 通过tcp udp控制通道
                if cmd.upper() == 'readerChannel'.upper():
                    channelState = list(map(int, data))
                    if self.configHandlers.machine.read('machine', 'hardwareType', 'string') == "F800":
                        channelState.extend([0, 0, 0, 0, 0, 0, 0, 0])  # f2000用
                    self.sendEvent('UART', 'uart_channelOpen', channelState)
                    continue

                if cmd == 'getReaderPower'.upper():
                    self.sendEvent("UI", "ui_socketGetReaderPower",[d] )
                    continue

                if cmd == 'getReaderChannel'.upper():
                    self.sendEvent("UI", "ui_socketGetReaderChannel", [])
                    continue

        if self.enRespond == 1:
            self.socketWorker.send(self.socketWorker.socketObj.rxBuf)
        self.socketWorker.socketObj.rxBuf = ''


def main(eventQ):
    while True:
        print("===================Socket task started===================")
        try:
            so = FeibotSocket(eventQ)
            so.work()
        except Exception as e:
            print(e)
            gtyTools.gtyLog.log.write(__file__, e, traceback.extract_stack())
